import type { ImagePreview } from '../index'
import { ToolKit } from '../../../../../lib/utils/toolkit'
import { logger } from '../../../../../types/constants'

export class ImagePreviewPreloadService {
  private readonly name: string = 'ImagePreviewPreloadService'
  private imagePreview: ImagePreview
  private preloadImageUrls: Map<string, boolean> = new Map()
  private isPreloading: boolean = false
  private preloadPromises: Map<string, Promise<void>> = new Map()

  constructor(instance: ImagePreview) {
    this.imagePreview = instance
  }

  destroy(): void {
    this.preloadImageUrls.clear()
    this.isPreloading = false
    this.preloadPromises.clear()
  }

  /**
   * 调度预加载
   */
  schedulePreload(): void {
    this.imagePreview.timerManager.createTimerTask({
      id: 'image-preview-preload',
      delay: 500,
      callback: this.preloadImagesToCache.bind(this),
    })
  }

  /**
   * 预加载图片到缓存（带锁机制）
   */
  async preloadImagesToCache(): Promise<void> {
    // 如果正在预加载，跳过
    if (this.isPreloading) {
      logger.debug(`[${this.name}] 预加载正在进行中，跳过`)
      return
    }

    this.isPreloading = true

    try {
      this.updatePreloadImageUrls()
      const needPreloadUrls = Object.keys(this.preloadImageUrls)
        .filter(url => this.preloadImageUrls.get(url) === true)

      if (needPreloadUrls.length === 0) {
        logger.debug(`[${this.name}] 没有需要预加载的图片`)
        return
      }

      // 使用并发控制，避免同时加载太多图片
      const BATCH_SIZE = 5
      for (let i = 0; i < needPreloadUrls.length; i += BATCH_SIZE) {
        const batchUrls = needPreloadUrls.slice(i, i + BATCH_SIZE)
        await Promise.allSettled(
          batchUrls.map(url => this.preloadSingleImage(url)),
        )
      }

      logger.info(`[${this.name}] ${needPreloadUrls.length} 张图片预加载完成`)
    }
    catch (error) {
      logger.error(`[${this.name}] 图片预加载失败:`, error)
    }
    finally {
      this.isPreloading = false
    }
  }

  /**
   * 预加载单张图片
   */
  private async preloadSingleImage(imageUrl: string): Promise<void> {
    // 检查是否已经在预加载中
    if (this.preloadPromises.has(imageUrl)) {
      return this.preloadPromises.get(imageUrl)
    }

    // 创建预加载 Promise
    const preloadPromise = (async () => {
      try {
        // 再次检查是否还需要预加载（可能被其他请求处理了）
        if (this.preloadImageUrls.get(imageUrl) !== true)
          return

        const info = await ToolKit.browser.file.getImageInfo(imageUrl)

        if (info) {
          this.imagePreview.updateImageCache(imageUrl, info)
          this.preloadImageUrls.set(imageUrl, false)
          logger.debug(`[${this.name}] 预加载成功: ${imageUrl}`)
        }
      }
      catch (error) {
        logger.warn(`[${this.name}] 预加载失败: ${imageUrl}`, error)
        this.preloadImageUrls.set(imageUrl, false)
      }
      finally {
        // 清理 Promise 引用
        this.preloadPromises.delete(imageUrl)
      }
    })()

    // 保存 Promise 引用
    this.preloadPromises.set(imageUrl, preloadPromise)
    return preloadPromise
  }

  /**
   * 更新预加载的图片 URL 列表
   */
  updatePreloadImageUrls(): void {
    this.imagePreview.uiService.previewElements.forEach((state) => {
      const { imageUrl } = state
      const preloadImageUrls = Object.keys(this.preloadImageUrls)

      if (imageUrl
        && state.preload !== true
        && !this.imagePreview.imageCache.has(imageUrl)
        && !preloadImageUrls.includes(imageUrl)
        && preloadImageUrls.length < this.imagePreview.config.maxPreloadCount) {
        this.preloadImageUrls.set(imageUrl, true)
        state.preload = true
      }
    })
  }
}
